package com.example.utils;

import io.jsonwebtoken.*;
import io.jsonwebtoken.io.Decoders;
import io.jsonwebtoken.security.Keys;
import org.springframework.util.StringUtils;

import java.security.Key;
import java.util.Date;
import java.util.Map;
import java.util.function.Function;

public class JwtHelper {

    // 配置参数
    private static final long TOKEN_EXPIRATION = 1000 * 60 * 60 * 24; // 24小时
    private static final String TOKEN_SIGN_KEY = "494013WjFSKUIUOTA287BB0028HBMBQU=321DF4WRWERQDWER89H7W66D7JNKJSHBF88320198QTA8JM295BNC289859H9N";     // 签名密钥

    // 获取安全的密钥对象
    private static Key getSigningKey() {
        byte[] keyBytes = Decoders.BASE64.decode(TOKEN_SIGN_KEY);
        return Keys.hmacShaKeyFor(keyBytes);
    }

    /**
     * 根据用户信息生成 JWT Token
     */
    public static String createToken(Integer userId, String userName) {
        return Jwts.builder()
                .setSubject("TLF-USER")
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + TOKEN_EXPIRATION))
                .claim("userId", userId)
                .claim("userName", userName)
                .signWith(getSigningKey(), SignatureAlgorithm.HS512)
                .compressWith(CompressionCodecs.GZIP)
                .compact();
    }

    /**
     * 解析并获取 Claims 主体内容
     */
    public static Claims extractClaims(String token) {
        if (StringUtils.isEmpty(token)) {
            throw new IllegalArgumentException("Token 不能为空");
        }
        try {
            return Jwts.parser()
                    .setSigningKey(getSigningKey())
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
        } catch (JwtException e) {
            throw new IllegalArgumentException("无效的 Token: " + e.getMessage());
        }
    }

    /**
     * 提取特定字段值（通用方法）
     */
    private static <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
        Claims claims = extractClaims(token);
        return claimsResolver.apply(claims);
    }

    /**
     * 判断 Token 是否过期
     */
    public static boolean isTokenExpired(String token) {
        return extractClaim(token, Claims::getExpiration).before(new Date());
    }

    /**
     * 获取用户ID
     */
    public static Integer getUserId(String token) {
        return extractClaim(token, claims -> (Integer) claims.get("userId"));
    }

    /**
     * 获取用户名
     */
    public static String getUserName(String token) {
        return extractClaim(token, claims -> (String) claims.get("userName"));
    }

    /**
     * 获取角色信息
     */
    public static String getUserRole(String token) {
        Object roleObj = extractClaim(token, claims -> claims.get("role"));
        return roleObj != null ? roleObj.toString() : null;
    }

    /**
     * 验证 Token 是否有效
     */
    public static boolean verifyToken(String token) {
        try {
            extractClaims(token);
            return true;
        } catch (IllegalArgumentException e) {
            return false;
        }
    }

    /**
     * 打印 Token 内容（调试用）
     */
    public static void resolveToken(String token) {
        Claims claims = extractClaims(token);
        System.out.println("Subject: " + claims.getSubject());
        System.out.println("Issued at: " + claims.getIssuedAt());
        System.out.println("Expiration: " + claims.getExpiration());
        for (Map.Entry<String, Object> entry : claims.entrySet()) {
            System.out.println(entry.getKey() + ": " + entry.getValue());
        }
    }

    public static void main(String[] args) {
        //String token1 = createToken(1, "admin", 1);
        //System.out.println("token1 = " + token1);
        String token = "eyJ6aXAiOiJHWklQIiwiYWxnIjoiSFM1MTIifQ.H4sIAAAAAAAA_6tWKi5NUrJSCvFx0w0Ndg1S0lHKTCxRsjI0NzUyMzY3MTfRUUqtKIALmBoDBUqLU4s8U4BiEKZfYm4q0IjElNzMPKD-ovwcINewFgBNgsY-WwAAAA.MvGKQaP_EdIw4NnbHCftBxS7SzJohwC7nNnIZTW6GoxQpJFoU612UkEnvVS5_B65CkxaKMH4GUlyLOhGkxBs2g";
        boolean b = verifyToken(token);
        System.out.println("b = " + b);
        boolean tokenExpired = isTokenExpired(token);
        System.out.println("tokenExpired = " + tokenExpired);
    }

}
